/*********************************************************************************
 *      Copyright:  (C) Guo Zixuan
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(06/04/25)
 *         Author: 	GUO Zixuan  <guozixuan@gmail.com>
 *      ChangeLog:  1, Release initial version on "06/04/25 16:39:35"
 *                 
 ********************************************************************************/
#include "main.h"

void print_usage(char *progname)
{
	printf("%s usingage:\n", progname);
	printf("-i(--ipaddr): sepcify server IP address.\n");
	printf("-p(--port): sepcify server port.\n");
	printf("-t(--samptime): sepcify socket samptime.\n");
	printf("-b(--background): running in daemon.\n");
	printf("-d(--debug): running in debug mode.\n");
	printf("-P(--Pack):data packing format, json or tlv\n");
	printf("-h(--help): print this help information.\n");

	return ;
}

int main(int argc, char **argv)
{
	float				temp;
	data_t 		 		data;
	char 	  			package[256];
	char				buf[1024];

	int					run_daemon = 0;
	char			   *log_file = "client.log";
	int					log_level =  LOG_LEVEL_INFO;
	char				*progname = NULL;
	char				*servip = NULL;
	int					port = 0;
	int                 status = 0;
	socket_ctx_t		socket_ctx;
	int					socketfd;
	int                 opt = -1 ;

	time_t				last_time;
	time_t				now_time;
	int					samp_time = 5;
	int 				has_sampled = 0;
	pack_proc_t         pack_proc = get_package;
	int					len = 0;

	sqlite3	   			*db;
	const char 			*db_name = "clientds18b20.db";
	char				first_data[64];
	struct option       long_options[]=
	{   
		{"ipaddr", required_argument, NULL, 'i'},
		{"port", required_argument, NULL, 'p'},
		{"samptime", required_argument, NULL, 't'},
		{"background", no_argument, NULL, 'b'},
		{"debug", no_argument, NULL, 'd'},
		{"Pack", required_argument, NULL, 'P'},
		{"help",no_argument,NULL,'h'},
		{NULL,0,NULL,0}
	};  
		
	progname = basename( argv[0] );
		
	while ( ( opt = getopt_long( argc, argv, "i:p:t:bdP:h", long_options, NULL) ) != -1 )
	{ 
		switch ( opt )
		{
			case 'i':
				servip = optarg;
				break;
			
			case 'p':
				port = atoi(optarg);
				break;
			
			case 't':
				samp_time = atoi(optarg);
				break;

			case 'b':
				run_daemon = 1;
				break;

			case 'd':
				log_file = "stdout";
				log_level = LOG_LEVEL_DEBUG;
				break;

			case 'P':
				if ( strcmp(optarg, "json") == 0 )
				{
					pack_proc = get_package_json;
				}
				else if ( strcmp(optarg, "tlv") == 0 )
				{
					pack_proc = get_package_tlv;
				}
				else
				{
					print_usage(argv[0]);
				}
				break;
			
			case 'h':
				print_usage(progname);
				return 0;
			
			default:
				break;
		}
	}

	if( !servip || !port || !samp_time )
	{
		print_usage(progname);
		return -1;
	}

	//初始化日志系统
	if( logger_init( log_file, log_level) < 0 )
	{
		log_error("initial logger system failure.\n");
		return -1;
	}

	//后台运行
	if( run_daemon )
	{
		daemon(1, 1);
		log_info("run daemon successfully.\n");
	}

	// 初始化 socket
	if( socket_init(&socket_ctx, servip, port) != 0)
	{
		log_error("Failed to initial socket.\n");
	}

	// 初始化数据库并创建表
	if (sqlite_init(&db, db_name) != 0) 
	{
		log_error("Failed to initialize database.\n");
	 	return -1;
	}

	last_time = 0;
	while (1) 
	{
		has_sampled = 0;

		// 第一步：判断时间是否到采样时间
		now_time = time(NULL);
		if (difftime(now_time, last_time) >= samp_time) 
		{
			last_time = now_time;// 更新上一次采样时间为当前时间
		
			memset(&data, 0, sizeof(data));
			memset(package, 0, sizeof(package));

			// 获取时间、温度、序列号，并打包成 package
			get_sn(data.sn, sizeof(data.sn));
			if (get_temp(&data.temp) != 0)
			{
				log_error("Failed to get temperature.\n");
				continue; 
			}
			get_time(data.mytime, sizeof(data.mytime));
		//	pack_proc(&data, package, sizeof(package));
		//	log_info("Sampled package: %s\n", package);
		
			pack_proc(&data, buf, sizeof(buf));
			log_info("Sampled package: %s\n", buf);
			has_sampled = 1; // 标记已经采样
		}

		// 第二步：判断 socket 连接状态
		if (socket_status(&socket_ctx) == 0) // Socket 断连
		{ 
			log_warning("client disconnected to server.\n");

			//尝试重新连接socket
			socket_close(&socket_ctx);
			if (socket_connect(&socket_ctx) < 0)
			{
				log_error("Failed to reconnect to server.\n");

				if (has_sampled) // 如果刚刚采样了
				{ 
					if (sqlite_insert_data(db, package) != 0) // 把数据存入数据库
					{	
						log_error("Failed to insert data into database.\n");
						continue;
					}
					log_info("Package inserted into database after socket disconnection.\n");
				}
				continue;
			}
			log_info("Reconnected to server successfully.\n");
		}
	
		// Socket 是连接状态
		if (has_sampled) // 如果刚刚采样了,则把package发送到server
		{
			len = pack_proc(&data, (uint8_t *)buf, sizeof(buf));
			if (write(socket_ctx.fd, (uint8_t *)buf, len) < 0)// 发送package数据到server失败
			{
				log_error("Failed to write data to server: %s\n", strerror(errno));
					
				// write失败，package存入数据库
				if (sqlite_insert_data(db, package) != 0) //存入失败
				{
					log_error("Failed to insert data into database.\n");
					continue;
				}
				log_info("Package inserted into database after failed write.\n");
				continue;
			}
				
			log_info("Package written to server successfully.\n");// 发送package数据到server成功
		}
			
		// 如果刚刚没有采样，则判断数据库内是否有数据
		if (sqlite_read_first_data(db, first_data, sizeof(first_data)) == 0)//成功读到第一条数据
		{
			log_info("Read first data from database: %s\n", first_data);
				
			len = pack_proc(&data, (uint8_t *)buf, sizeof(buf));
			if (write(socket_ctx.fd, (uint8_t *)buf, len) < 0) //write第一条数据到server失败
			{
				log_error("Failed to write data to server: %s\n", strerror(errno));
			}
			else//write第一条数据到server成功
			{ 
				log_info("Data from database written to server successfully.\n");

				if (sqlite_delete_first_data(db) != 0)//删除第一条数据失败 
				{
					log_error("Failed to delete first data from database.\n");
					continue;
				}
				log_info("Deleted first data from database.\n");
			}
		}

	usleep(100000); // 休眠 100ms防止cpu占用过高
	}

	sqlite_close_db(db); 
	socket_close(&socket_ctx);

	return 0;
}

